

struct imx6ull_lcdif{
    volatile unsigned int CTRL;                              
    volatile unsigned int CTRL_SET;                        
    volatile unsigned int CTRL_CLR;                         
    volatile unsigned int CTRL_TOG;                         
    volatile unsigned int CTRL1;                             
    volatile unsigned int CTRL1_SET;                         
    volatile unsigned int CTRL1_CLR;                       
    volatile unsigned int CTRL1_TOG;                       
    volatile unsigned int CTRL2;                            
    volatile unsigned int CTRL2_SET;                       
    volatile unsigned int CTRL2_CLR;                        
    volatile unsigned int CTRL2_TOG;                        
    volatile unsigned int TRANSFER_COUNT;   
         unsigned char RESERVED_0[12];
    volatile unsigned int CUR_BUF;                          
         unsigned char RESERVED_1[12];
    volatile unsigned int NEXT_BUF;                        
         unsigned char RESERVED_2[12];
    volatile unsigned int TIMING;                          
         unsigned char RESERVED_3[12];
    volatile unsigned int VDCTRL0;                         
    volatile unsigned int VDCTRL0_SET;                      
    volatile unsigned int VDCTRL0_CLR;                     
    volatile unsigned int VDCTRL0_TOG;                     
    volatile unsigned int VDCTRL1;                          
         unsigned char RESERVED_4[12];
    volatile unsigned int VDCTRL2;                          
         unsigned char RESERVED_5[12];
    volatile unsigned int VDCTRL3;                          
         unsigned char RESERVED_6[12];
    volatile unsigned int VDCTRL4;                           
         unsigned char RESERVED_7[12];
    volatile unsigned int DVICTRL0;    
           unsigned char RESERVED_8[12];
    volatile unsigned int DVICTRL1;                         
         unsigned char RESERVED_9[12];
    volatile unsigned int DVICTRL2;                        
         unsigned char RESERVED_10[12];
    volatile unsigned int DVICTRL3;                        
         unsigned char RESERVED_11[12];
    volatile unsigned int DVICTRL4;                          
         unsigned char RESERVED_12[12];
    volatile unsigned int CSC_COEFF0;  
           unsigned char RESERVED_13[12];
    volatile unsigned int CSC_COEFF1;                        
         unsigned char RESERVED_14[12];
    volatile unsigned int CSC_COEFF2;                        
         unsigned char RESERVED_15[12];
    volatile unsigned int CSC_COEFF3;                        
         unsigned char RESERVED_16[12];
    volatile unsigned int CSC_COEFF4;   
           unsigned char RESERVED_17[12];
    volatile unsigned int CSC_OFFSET;  
         unsigned char RESERVED_18[12];
    volatile unsigned int CSC_LIMIT;  
         unsigned char RESERVED_19[12];
    volatile unsigned int DATA;                              
         unsigned char RESERVED_20[12];
    volatile unsigned int BM_ERROR_STAT;                     
         unsigned char RESERVED_21[12];
    volatile unsigned int CRC_STAT;                        
         unsigned char RESERVED_22[12];
    volatile  unsigned int STAT;                             
         unsigned char RESERVED_23[76];
    volatile unsigned int THRES;                             
         unsigned char RESERVED_24[12];
    volatile unsigned int AS_CTRL;                           
         unsigned char RESERVED_25[12];
    volatile unsigned int AS_BUF;                            
         unsigned char RESERVED_26[12];
    volatile unsigned int AS_NEXT_BUF;                     
         unsigned char RESERVED_27[12];
    volatile unsigned int AS_CLRKEYLOW;                    
         unsigned char RESERVED_28[12];
    volatile unsigned int AS_CLRKEYHIGH;                   
         unsigned char RESERVED_29[12];
    volatile unsigned int SYNC_DELAY;                      
};

static int lcd_controller_init(struct imx6ull_lcdif *lcdif, struct display_timing *dt, int lcd_bpp, int fb_bpp, unsigned int fb_phy)
{
    int lcd_data_bus_width;
    int fb_width;
    int vsync_pol = 0;
    int hsync_pol = 0;
    int de_pol = 0;
    int clk_pol = 0;

    if (dt->flag & DISPLAY_FLAGS_HSYNC_HIGH){
        hsync_pol = 1;
    }
    if (dt->flag & DISPLAY_FLAGS_VSYNC_HIGH){
        vsync_pol = 1;
    }
    if (dt->flag & DISPLAY_FLAGS_DE_HIGH){
        de_pol = 1;
    }
    if (dt->flag & DISPLAY_FLAGS_PIXDATA_POSEDGE){
        clk_pol = 1;
    }
    
    

    if (lcd_bpp == 24)
        lcd_data_bus_width = 0x3;
    else if (lcd_bpp == 18)
        lcd_data_bus_width = 0x2;
    else if (lcd_bpp == 8)
        lcd_data_bus_width = 0x1;   
    else if (lcd_bpp == 16)
        lcd_data_bus_width = 0x0;
    else
        return -1;

    if (fb_bpp == 24)
        fb_width = 0x3;
    else if (fb_bpp == 18)
        fb_width = 0x2;
    else if (fb_bpp == 8)
        fb_width = 0x1;   
    else if (fb_bpp == 16)
        fb_width = 0x0;
    else
        return -1;   
    
	/* 
     * 初始化LCD控制器的CTRL寄存器
     * [19]       :  1      : DOTCLK和DVI modes需要设置为1 
     * [17]       :  1      : 设置为1工作在DOTCLK模式
     * [15:14]    : 00      : 输入数据不交换（小端模式）默认就为0，不需设置
     * [13:12]    : 00      : CSC数据不交换（小端模式）默认就为0，不需设置
     * [11:10]    : 11		: 数据总线为24bit
     * [9:8]    根据显示屏资源文件bpp来设置：8位0x1 ， 16位0x0 ，24位0x3
     * [5]        :  1      : 设置elcdif工作在主机模式
     * [1]        :  0      : 24位数据均是有效数据，默认就为0，不需设置
	 */	
    lcdif->CTRL = (0<<30) | (0<<29) | (0<<28) | (1<<19) | (1<<17) | (lcd_data_bus_width<<10) | (fb_width<<8) | (1<<5);

    /*
    * 设置Elcdif的寄存器CTRL1
    * 根据bpp设置，bpp为24或32才设置
    * [19:16]  : 111  :表示ARGB传输格式模式下，传输24位无压缩数据，A通道不用传输）
    */	
	 if(fb_bpp == 24 || fb_bpp == 32)
	 {		
        lcdif->CTRL1 &= ~(0xf << 16); //16-19位先清零
        lcdif->CTRL1 |=  (0x7 << 16); //在设置为0111
	 }
     else
     {
        lcdif->CTRL1 |= (0xf<<16);
     }
	 	
    /*
    * 设置Elcdif的寄存器TRANSFER_COUNT寄存器
    * [31:16]  : 垂直方向上的像素个数  
    * [15:0]   : 水平方向上的像素个数
    */
    lcdif->TRANSFER_COUNT  = (dt->vactive.typ << 16) | (dt->hactive.typ << 0);

	/*
    * 设置Elcdif的VDCTRL0寄存器
    * [29] 0 : VSYNC输出  ，默认为0，无需设置
    * [28] 1 : 在DOTCLK模式下，设置1硬件会产生使能ENABLE输出
    * [27] 0 : VSYNC低电平有效  ,根据屏幕配置文件将其设置为0
    * [26] 0 : HSYNC低电平有效 , 根据屏幕配置文件将其设置为0
    * [25] 1 : DOTCLK下降沿有效 ，根据屏幕配置文件将其设置为1
    * [24] 1 : ENABLE信号高电平有效，根据屏幕配置文件将其设置为1
    * [21] 1 : 帧同步周期单位，DOTCLK mode设置为1
    * [20] 1 : 帧同步脉冲宽度单位，DOTCLK mode设置为1
    * [17:0] :  vysnc脉冲宽度 
    */
    lcdif->VDCTRL0 = (1 << 28)|(vsync_pol << 27)\
                    | (hsync_pol << 26)\
                    | (clk_pol << 25)\
                    | (de_pol << 24)\
                    | (1 << 21)|(1 << 20)|(dt->vsync_len.typ << 0);

	/*
    * 设置Elcdif的VDCTRL1寄存器
    * 设置垂直方向的总周期:上黑框tvb+垂直同步脉冲tvp+垂直有效高度yres+下黑框tvf
    */  	
    lcdif->VDCTRL1 = dt->vback_porch.typ + dt->vsync_len.typ + dt->vactive.typ + dt->vfront_porch.typ; 

    /*
    * 设置Elcdif的VDCTRL2寄存器
    * [18:31]  : 水平同步信号脉冲宽度
    * [17: 0]   : 水平方向总周期
    * 设置水平方向的总周期:左黑框thb+水平同步脉冲thp+水平有效高度xres+右黑框thf
    */ 

    lcdif->VDCTRL2 = (dt->hsync_len.typ << 18) | (dt->hback_porch.typ + dt->hsync_len.typ + dt->hactive.typ + dt->hfront_porch.typ);

    /*
    * 设置Elcdif的VDCTRL3寄存器
    * [27:16] ：水平方向上的等待时钟数 =thb + thp
    * [15:0]  : 垂直方向上的等待时钟数 = tvb + tvp
    */ 
    
    lcdif->VDCTRL3 = ((dt->hback_porch.typ + dt->hsync_len.typp) << 16) | (dt->vback_porch.typ + dt->vsync_len.typ);

    /*
    * 设置Elcdif的VDCTRL4寄存器
    * [18]     使用VSHYNC、HSYNC、DOTCLK模式此为置1
    * [17:0]  : 水平方向的宽度
    */ 

    lcdif->VDCTRL4 = (1<<18) | (dt->hactive.typ);

    /*
    * 设置Elcdif的CUR_BUF和NEXT_BUF寄存器
    * CUR_BUF    :  当前显存地址
    * NEXT_BUF :    下一帧显存地址
    * 方便运算，都设置为同一个显存地址
    */ 
	  
	lcdif->CUR_BUF  =  fb_phy;
    lcdif->NEXT_BUF =  fb_phy;
}